/*
 * @Description: 类的修饰符
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2021-04-30 13:51:33
 * @LastEditTime: 2021-04-30 18:44:42
 */
var __extends = (this && this.__extends) || (function() {
	var extendStatics = function(d, b) {
		extendStatics = Object.setPrototypeOf ||
			({
					__proto__: []
				}
				instanceof Array && function(d, b) {
					d.__proto__ = b;
				}) ||
			function(d, b) {
				for (var p in b)
					if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
			};
		return extendStatics(d, b);
	};
	return function(d, b) {
		if (typeof b !== "function" && b !== null)
			throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
		extendStatics(d, b);

		function __() {
			this.constructor = d;
		}
		d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	};
})();
/**
 * 修饰符用来描述类中成员的可访问性
 * 主要包含：public,private,protected,readonly,static,get,set
 * get和set官方说法是类中的存取器（用于劫持读写），编译为js后是使用Object.defineProperty方法
 * 注意：在ES6中的提案 #号开头的私有属性并不支持
 */
/**
 * public 公共属性/方法，在当前类、子类、外部实例都可以访问。默认状态都是公共的，所以public可以省略
 * private 私有属性/方法，只能在当前类中使用。在子类和外部均不可使用
 * protected 受保护的属性/方法，只能在当前类及其派生类中访问
 * readonly 只读属性，初始化赋值之后就不能修改（除了初始化，任何地方都不能改），和const作用类似
 * static 静态属性/方法，类可以直接调用无需实例化，另外，构造函数是不能用static修饰的
 * get 监听到读取方法，可以做一些事,读的时候无需执行此方法，可以直接读（无需执行，可以看做一个属性）和vue计算属性差不多
 * set 监听到写入方法，可以做一些事，get和set关键字只能用于在方法前面
 */
/**
 * get 和 set 访问器必须属于同一类型（get的返回值类型和set的参数类型一致）。
 * set 存储器必须正好具有一个参数。（因为要使用=号赋值，只能赋值一个值）
 * readonly 修饰符有特殊的特性：如果在构造函数的参数中使用readonly，则会默认在类中声明一个属性，就无需再次申明，如下User类中的id参数
 */
(function() {
	var User = /** @class */ (function() {
		function User(name, money, age, sex, id) {
			if (sex === void 0) {
				sex = '男';
			}
			if (id === void 0) {
				id = Date.now();
			}
			this.id = id;
			this.name = name;
			this.money = money;
			this.age = age;
			this.sex = sex;
		}
		// 静态方法
		User.getState = function() {
			return User.state;
		};
		Object.defineProperty(User.prototype, "myMoney", {
			// 读取方法
			get: function() {
				// return this.money + "元" // 报错：不能将类型“string”分配给类型“number”
				return this.money + "元";
			},
			// 写入方法
			set: function(money) {
				// this.money = money // 报错：不能将类型“string”分配给类型“number”
				this.money = Number(money);
			},
			enumerable: false,
			configurable: true
		});
		User.state = 1; // 静态属性
		return User;
	}());
	var Admin = /** @class */ (function(_super) {
		__extends(Admin, _super);

		function Admin() {
			return _super !== null && _super.apply(this, arguments) || this;
		}
		Object.defineProperty(Admin.prototype, "nextAge", {
			// get getMoney() {
			//     return this.money // 报错：属性“money”为私有属性，只能在类“User”中访问。
			// }
			get: function() {
				console.log("执行了get");
				return this.age + 1; // 受保护的属性在子类中可以读写
			},
			set: function(age) {
				this.age = age;
				console.log("执行了set"); // 受保护的属性在子类中可以读写
			},
			enumerable: false,
			configurable: true
		});
		Admin.prototype.getSex = function() {
			return this.sex;
		};
		return Admin;
	}(User));
	var admin = new Admin("小明", 100, 15);
	console.log(admin.nextAge); // 执行了get 16
	admin.nextAge = 10; // 执行了set
	console.log(admin.nextAge); // 执行了get 11
	// console.log(admin.age) // 报错：属性“age”受保护，只能在类“User”及其子类中访问。
	admin.money = 9999
	console.log(admin.money) // 报错：属性“money”为私有属性，只能在类“User”中访问。
	console.log(admin.myMoney); // 100元
	admin.myMoney = "1000";
	console.log(admin.myMoney); // 1000元
	console.log(admin.getSex()); // 男
	admin.sex = "女" //报错：无法分配到 "sex" ，因为它是只读属性。
	console.log("====admin.sex", admin.sex)
	console.log(admin.id); // 1619775257212
	console.log("=================================");
	console.log(User.state); // 1
	User.state = 2;
	console.log(User.getState()); // 2
	console.log("=================================");
	/**
	 * geter和seter练习
	 */
	var Persion = /** @class */ (function() {
		function Persion(firstName, lastName) {
			this.firstName = firstName;
			this.lastName = lastName;
		}
		Object.defineProperty(Persion.prototype, "fullName", {
			// 访问器
			get: function() {
				var _a = this,
					firstName = _a.firstName,
					lastName = _a.lastName;
				return firstName + "-" + lastName;
			},
			// 存储器
			set: function(val) {
				console.log("触发了存储器");
				var _a = val.split("-"),
					firstName = _a[0],
					lastName = _a[1];
				this.firstName = firstName;
				this.lastName = lastName;
			},
			enumerable: false,
			configurable: true
		});
		return Persion;
	}());
	var p1 = new Persion("东方", "不败");
	console.log(p1); //{firstName: '东方', lastName: '不败'}
	console.log(p1.fullName); // 东方-不败 ,这个属性会被创建到prototype中
	p1.fullName = "令狐-冲"; // 触发了存储器
	console.log(p1.fullName); // 令狐-冲
})();
